package com.example.mattrigle;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class CornerDrawable extends BitmapDrawable implements
		CustomAnimation.TimerListener {
	// ==========================================================
	// Field
	// ==========================================================
	private static String local_path = null;
	private boolean decoded;
	private static Bitmap mTmpBitmap;
	private int height, width;
	private CustomAnimation anim = new CustomAnimation();

	private boolean pressed = false;
	private boolean is_runtime_message = false;
	private float messageElapsedTime = 0;
	private long fade_in_alert_message_time = 400L;
	private long fade_out_alert_message_time = 400L;
	private long cooldown_alert_message_time = 10000L;
	private int alert_message_alpha = 0;

	private static enum AnimteState {
		FadeIn, Progress, FadeOut
	};

	private AnimteState anim_state = AnimteState.FadeIn;

	private View view = null;
	private Drawable alertDrawable = null;
	private int alert_width = 0, alert_height = 0;
	private String[] labels = null;
	private Rect foregroundRect = null;
	private Rect alertRect = new Rect();
	private Paint labelPaint = new Paint();
	private Point labelPoint = new Point(0, 0);

	private float aw = 1f;

	public void setSmoothScale(float aw) {
		this.aw = aw;
		labelPaint.setTextSize(aw * 25f);
		float aspectRatio = ((float) alertDrawable.getIntrinsicWidth())
				/ alertDrawable.getIntrinsicHeight();
		alert_width = (int) (labelPaint.measureText(labels[0]) * 1.3);
		alert_height = (int) (alert_width * aspectRatio);

		labelPoint.x = alertRect.left
				+ (int) (labelPaint.measureText(labels[0]) * 0.2);
		labelPoint.y = alertRect.top
				+ ((int) (alertRect.height() * 0.8) - (int) (labelPaint
						.measureText(labels[0]) * 0.15)) / 2;

	}

	static String folder = null;

	// ==========================================================
	// Constructor
	// ==========================================================
	public static String getLocalPath(Context _context) {
		if (local_path == null) {
			folder = Environment.getExternalStorageDirectory()
					.getAbsolutePath()
					+ "/Android/data/"
					+ _context.getApplicationContext().getPackageName() + "/";
			File dir = new File(folder);
			dir.mkdirs();

			local_path = folder + '/' + "corner_image.png";
		}

		return local_path;
	}

	public CornerDrawable(View view, File f) throws IOException {
		this(view, f, false);
	}

	public CornerDrawable(View view, InputStream is) throws IOException {
		this(view, is, false);
	}

	public CornerDrawable(View view, File f, boolean inline) throws IOException {
		this(view, new BufferedInputStream(new FileInputStream(f), 32768),
				inline);
	}

	static Typeface face = null;

	@SuppressWarnings({ "deprecation", "static-access" })
	public CornerDrawable(View view, InputStream is, boolean inline)
			throws IOException {
		super();
		this.view = view;

		local_path = this.getLocalPath(view.getContext());
		File file = new File(local_path);

		if (is == null) {
			is = new FileInputStream(file);
		}

		BufferedInputStream bufferedInputStream = new BufferedInputStream(is);
		mTmpBitmap = BitmapFactory.decodeStream(bufferedInputStream);

		if (!file.exists()) {
			FileOutputStream fout = new FileOutputStream(file);
			mTmpBitmap.compress(Bitmap.CompressFormat.PNG, 100, fout);
		}
		face = Typeface.createFromAsset(view.getContext().getAssets(),
					"fonts/THA0085.ttf");
		labelPaint.setTypeface(face);
		String label = view.getResources().getString(
				R.string.alert_corner_touch);
		labels = label.split(",");
		alertDrawable = view.getResources().getDrawable(R.raw.ballon_speak);

		labelPaint.setTextSize(32);
		float aspectRatio = ((float) alertDrawable.getIntrinsicWidth())
				/ alertDrawable.getIntrinsicHeight();
		alert_width = (int) (labelPaint.measureText(labels[0]) * 1.3);
		alert_height = (int) (alert_width / aspectRatio);

		labelPaint.setColor(0xff383838);

		decoded = false;

		height = mTmpBitmap.getHeight();
		width = mTmpBitmap.getWidth();
		setVisible(true, true);

		decoded = true;
	}

	// ==========================================================
	// Properties
	// ==========================================================
	public boolean isDecoded() {
		return decoded;
	}

	@Override
	public int getMinimumHeight() {
		return height;
	}

	@Override
	public int getMinimumWidth() {
		return width;
	}

	@Override
	public int getIntrinsicHeight() {
		return height;
	}

	@Override
	public int getIntrinsicWidth() {
		return width;
	}

	public void setForeground(Rect rect) {
		foregroundRect = rect;
		alertRect.left = foregroundRect.left + 50;
		alertRect.top = foregroundRect.centerY() - alert_height
				+ (int) (alert_height * 0.4);
		alertRect.bottom = foregroundRect.centerY();
		alertRect.right = alertRect.left + (int) (alert_width * 1.2);

		if (alertRect.top < 10) {
			alertRect.bottom += Math.abs(alertRect.top) / +10;
			alertRect.top = 10;
		}

		labelPoint.x = alertRect.left
				+ (int) (labelPaint.measureText(labels[0]) * 0.3);
		labelPoint.y = alertRect.top
				+ ((int) (alertRect.height() * 0.5) - (int) (labelPaint
						.measureText(labels[0]) * 0.15)) / 2;

		alertDrawable.setBounds(alertRect);
	}

	// ==========================================================
	// Process & Operand Method
	// ==========================================================
	private Rect getSourceRect() {
		return new Rect(0, 0, mTmpBitmap.getWidth(), mTmpBitmap.getHeight());
	}

	private Bitmap getFrameBitmap() {
		return mTmpBitmap;
	}

	private void startAlertMessage() {
		is_runtime_message = true;
		messageElapsedTime = 0;
		anim_state = AnimteState.FadeIn;
	}

	// ==========================================================
	// Public Method
	// ==========================================================

	public void start() {

		if (!this.isDecoded())
			return;

		anim.setInterval(1000);
		anim.setListener(this);
		anim.StartAnimation();

		if (view != null)
			view.postInvalidate();
	}

	public void stop() {
		if (anim != null)
			anim.StopAnimation();
	}

	public void finish() {
		try {
			decoded = false;
			if (decoded) {
				if (alertDrawable != null)
					((BitmapDrawable) this.alertDrawable).getBitmap().recycle();
				if (mTmpBitmap != null)
					this.mTmpBitmap.recycle();
			}
		} catch (Exception e) {
		}
	}

	// ==========================================================
	// Event Method
	// ==========================================================
	public boolean onTouch(int action, int x, int y) {
		if (!isDecoded())
			return false;
		try{
		if (action == MotionEvent.ACTION_DOWN) {
			if (foregroundRect.left < x && foregroundRect.right > x
					&& foregroundRect.top < y && foregroundRect.bottom > y) {
				if (!pressed) {
					startAlertMessage();
					pressed = true;
				}
				return true;
			}
		}
		if (action == MotionEvent.ACTION_UP
				|| action == MotionEvent.ACTION_CANCEL) {
			pressed = false;
		}
		}catch(Exception e){}
		return false;
	}

	public void Draw(Canvas canvas) {
		try {
			if (this.isDecoded()) {

				canvas.drawBitmap(getFrameBitmap(), getSourceRect(),
						foregroundRect, new Paint());
				if (pressed || is_runtime_message) {
					if (view != null) {
						Log.e("Math", "Draw(Canvas canvas) ;"
								+ alert_message_alpha);
					}

					alertDrawable.setAlpha(alert_message_alpha);
					labelPaint.setAlpha(alert_message_alpha);

					alertDrawable.draw(canvas);
					for (int i = 0; i < labels.length; i++)
						canvas.drawText(labels[i], labelPoint.x, labelPoint.y
								+ (aw * 18 * i), labelPaint);
				}

			}
		} catch (Exception e) {
		}
	}

	@Override
	public void onTimeUpdate(CustomAnimation obj, long totalTime, long deltaTime) {

		if (!isDecoded())
			return;
		if (pressed || is_runtime_message) {
			Log.e("Math", "if(pressed||is_runtime_message)"
					+ messageElapsedTime);

			messageElapsedTime += deltaTime;
			switch (anim_state) {
			case FadeIn:
				alert_message_alpha = (int) ((messageElapsedTime / (float) fade_in_alert_message_time) * 255f);
				if (messageElapsedTime > fade_in_alert_message_time) {
					Log.e("Math", "anim_state = AnimteState.Progress;");
					messageElapsedTime = 0;
					anim_state = AnimteState.Progress;
				}
				break;
			case Progress:
				if (messageElapsedTime > cooldown_alert_message_time) {
					Log.e("Math", "anim_state = AnimteState.FadeOut");
					messageElapsedTime = cooldown_alert_message_time;
					if (!pressed) {
						messageElapsedTime = 0;
						anim_state = AnimteState.FadeOut;
					}
				}
				break;
			case FadeOut:
				alert_message_alpha = (int) (((float) (fade_out_alert_message_time - messageElapsedTime) / (float) fade_out_alert_message_time) * 255f);
				if (messageElapsedTime > fade_out_alert_message_time) {
					Log.e("Math", "anim_state = AnimteState.FadeIn;");
					anim_state = AnimteState.FadeIn;
					is_runtime_message = false;
					pressed = false;
					obj.EndAnimation();
				}
				break;
			}
			if (alert_message_alpha > 255)
				alert_message_alpha = 255;

			if (view != null) {
				Log.e("Math", "view.postInvalidate();");
				view.postInvalidate();
			}
		}
	}

}
